Using LSTMs, CNNs, GRUs with a larger dataset

In this colab, you use different kinds of layers to see how they affect the model.

You will use the glue/sst2 dataset, which is available through tensorflow_datasets.

The General Language Understanding Evaluation (GLUE) benchmark (https://gluebenchmark.com/) is a collection of resources for training, evaluating, and analyzing natural language understanding systems.

These resources include the Stanford Sentiment Treebank (SST) dataset that consists of sentences from movie reviews and human annotations of their sentiment. This colab uses version 2 of the SST dataset.

The splits are:

  • train 67,349
  • validation 872

and the column headings are:

  • sentence
  • label

For more information about the dataset, see https://www.tensorflow.org/datasets/catalog/glue#gluesst2

In [1]:
import tensorflow as tf
import tensorflow_datasets as tfds

import numpy as np

Get the dataset

In [2]:
# Get the dataset.
# It has 70000 items, so might take a while to download
dataset, info = tfds.load('glue/sst2', with_info=True)
print(info.features)
print(info.features["label"].num_classes)
print(info.features["label"].names)
Downloading and preparing dataset glue/sst2/1.0.0 (download: 7.09 MiB, generated: Unknown size, total: 7.09 MiB) to /root/tensorflow_datasets/glue/sst2/1.0.0...
/usr/local/lib/python3.6/dist-packages/urllib3/connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)





Shuffling and writing examples to /root/tensorflow_datasets/glue/sst2/1.0.0.incompleteQNAJNR/glue-train.tfrecord
Shuffling and writing examples to /root/tensorflow_datasets/glue/sst2/1.0.0.incompleteQNAJNR/glue-validation.tfrecord
Shuffling and writing examples to /root/tensorflow_datasets/glue/sst2/1.0.0.incompleteQNAJNR/glue-test.tfrecord
Dataset glue downloaded and prepared to /root/tensorflow_datasets/glue/sst2/1.0.0. Subsequent calls will reuse this data.
FeaturesDict({
    'idx': tf.int32,
    'label': ClassLabel(shape=(), dtype=tf.int64, num_classes=2),
    'sentence': Text(shape=(), dtype=tf.string),
})
2
['negative', 'positive']
In [3]:
# Get the training and validation datasets
dataset_train, dataset_validation = dataset['train'], dataset['validation']
dataset_train
Out[3]:
<DatasetV1Adapter shapes: {idx: (), label: (), sentence: ()}, types: {idx: tf.int32, label: tf.int64, sentence: tf.string}>
In [4]:
# Print some of the entries
for example in dataset_train.take(2):  
  review, label = example["sentence"], example["label"]
  print("Review:", review)
  print("Label: %d \n" % label.numpy())
Review: tf.Tensor(b'for the uninitiated plays better on video with the sound ', shape=(), dtype=string)
Label: 0 

Review: tf.Tensor(b'like a giant commercial for universal studios , where much of the action takes place ', shape=(), dtype=string)
Label: 0 

In [5]:
# Get the sentences and the labels
# for both the training and the validation sets
training_reviews = []
training_labels = []
 
validation_reviews = []
validation_labels = []

# The dataset has 67,000 training entries, but that's a lot to process here!

# If you want to take the entire dataset: WARNING: takes longer!!
# for item in dataset_train.take(-1):

# Take 10,000 reviews
for item in dataset_train.take(10000):
  review, label = item["sentence"], item["label"]
  training_reviews.append(str(review.numpy()))
  training_labels.append(label.numpy())

print ("\nNumber of training reviews is: ", len(training_reviews))

# print some of the reviews and labels
for i in range(0, 2):
  print (training_reviews[i])
  print (training_labels[i])

# Get the validation data
# there's only about 800 items, so take them all
for item in dataset_validation.take(-1):  
  review, label = item["sentence"], item["label"]
  validation_reviews.append(str(review.numpy()))
  validation_labels.append(label.numpy())

print ("\nNumber of validation reviews is: ", len(validation_reviews))

# Print some of the validation reviews and labels
for i in range(0, 2):
  print (validation_reviews[i])
  print (validation_labels[i])
Number of training reviews is:  10000
b'for the uninitiated plays better on video with the sound '
0
b'like a giant commercial for universal studios , where much of the action takes place '
0

Number of validation reviews is:  872
b'a valueless kiddie paean to pro basketball underwritten by the nba . '
0
b"featuring a dangerously seductive performance from the great daniel auteuil , `` sade '' covers the same period as kaufmann 's `` quills '' with more unsettlingly realistic results . "
1

Tokenize the words and sequence the sentences

In [6]:
# There's a total of 21224 words in the reviews
# but many of them are irrelevant like with, it, of, on.
# If we take a subset of the training data, then the vocab
# will be smaller.

# A reasonable review might have about 50 words or so,
# so we can set max_length to 50 (but feel free to change it as you like)

vocab_size = 4000
embedding_dim = 16
max_length = 50
trunc_type='post'
pad_type='post'
oov_tok = "<OOV>"

from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences

tokenizer = Tokenizer(num_words = vocab_size, oov_token=oov_tok)
tokenizer.fit_on_texts(training_reviews)
word_index = tokenizer.word_index

Pad the sequences

In [7]:
# Pad the sequences so that they are all the same length
training_sequences = tokenizer.texts_to_sequences(training_reviews)
training_padded = pad_sequences(training_sequences,maxlen=max_length, 
                                truncating=trunc_type, padding=pad_type)

validation_sequences = tokenizer.texts_to_sequences(validation_reviews)
validation_padded = pad_sequences(validation_sequences,maxlen=max_length)

training_labels_final = np.array(training_labels)
validation_labels_final = np.array(validation_labels)

Create the model using an Embedding

In [8]:
model = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
    tf.keras.layers.GlobalAveragePooling1D(),  
    tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (None, 50, 16)            64000     
_________________________________________________________________
global_average_pooling1d (Gl (None, 16)                0         
_________________________________________________________________
dense (Dense)                (None, 1)                 17        
=================================================================
Total params: 64,017
Trainable params: 64,017
Non-trainable params: 0
_________________________________________________________________

Train the model

In [9]:
num_epochs = 20
history = model.fit(training_padded, training_labels_final, epochs=num_epochs, 
                    validation_data=(validation_padded, validation_labels_final))
Epoch 1/20
313/313 [==============================] - 1s 4ms/step - loss: 0.6830 - accuracy: 0.5591 - val_loss: 0.6879 - val_accuracy: 0.5183
Epoch 2/20
313/313 [==============================] - 1s 3ms/step - loss: 0.6709 - accuracy: 0.5751 - val_loss: 0.6693 - val_accuracy: 0.6124
Epoch 3/20
313/313 [==============================] - 1s 3ms/step - loss: 0.6505 - accuracy: 0.6296 - val_loss: 0.6455 - val_accuracy: 0.6399
Epoch 4/20
313/313 [==============================] - 1s 3ms/step - loss: 0.6218 - accuracy: 0.6695 - val_loss: 0.6136 - val_accuracy: 0.6950
Epoch 5/20
313/313 [==============================] - 1s 3ms/step - loss: 0.5889 - accuracy: 0.7097 - val_loss: 0.5820 - val_accuracy: 0.7236
Epoch 6/20
313/313 [==============================] - 1s 3ms/step - loss: 0.5554 - accuracy: 0.7425 - val_loss: 0.5554 - val_accuracy: 0.7202
Epoch 7/20
313/313 [==============================] - 1s 4ms/step - loss: 0.5242 - accuracy: 0.7706 - val_loss: 0.5351 - val_accuracy: 0.7489
Epoch 8/20
313/313 [==============================] - 1s 3ms/step - loss: 0.4950 - accuracy: 0.7927 - val_loss: 0.5198 - val_accuracy: 0.7351
Epoch 9/20
313/313 [==============================] - 1s 3ms/step - loss: 0.4698 - accuracy: 0.8038 - val_loss: 0.5034 - val_accuracy: 0.7592
Epoch 10/20
313/313 [==============================] - 1s 3ms/step - loss: 0.4461 - accuracy: 0.8213 - val_loss: 0.4957 - val_accuracy: 0.7592
Epoch 11/20
313/313 [==============================] - 1s 4ms/step - loss: 0.4250 - accuracy: 0.8307 - val_loss: 0.4889 - val_accuracy: 0.7592
Epoch 12/20
313/313 [==============================] - 1s 4ms/step - loss: 0.4066 - accuracy: 0.8373 - val_loss: 0.4861 - val_accuracy: 0.7672
Epoch 13/20
313/313 [==============================] - 1s 4ms/step - loss: 0.3907 - accuracy: 0.8404 - val_loss: 0.4849 - val_accuracy: 0.7615
Epoch 14/20
313/313 [==============================] - 1s 3ms/step - loss: 0.3750 - accuracy: 0.8469 - val_loss: 0.4868 - val_accuracy: 0.7661
Epoch 15/20
313/313 [==============================] - 1s 3ms/step - loss: 0.3611 - accuracy: 0.8552 - val_loss: 0.4911 - val_accuracy: 0.7603
Epoch 16/20
313/313 [==============================] - 1s 3ms/step - loss: 0.3486 - accuracy: 0.8553 - val_loss: 0.4939 - val_accuracy: 0.7649
Epoch 17/20
313/313 [==============================] - 1s 3ms/step - loss: 0.3376 - accuracy: 0.8623 - val_loss: 0.4985 - val_accuracy: 0.7661
Epoch 18/20
313/313 [==============================] - 1s 3ms/step - loss: 0.3271 - accuracy: 0.8649 - val_loss: 0.5023 - val_accuracy: 0.7764
Epoch 19/20
313/313 [==============================] - 1s 4ms/step - loss: 0.3173 - accuracy: 0.8684 - val_loss: 0.5131 - val_accuracy: 0.7615
Epoch 20/20
313/313 [==============================] - 1s 3ms/step - loss: 0.3082 - accuracy: 0.8707 - val_loss: 0.5176 - val_accuracy: 0.7729

Plot the accurracy and loss

In [10]:
import matplotlib.pyplot as plt


def plot_graphs(history, string):
  plt.plot(history.history[string])
  plt.plot(history.history['val_'+string])
  plt.xlabel("Epochs")
  plt.ylabel(string)
  plt.legend([string, 'val_'+string])
  plt.show()
  
plot_graphs(history, "accuracy")
plot_graphs(history, "loss")

Write a function to predict the sentiment of reviews

In [11]:
# Write some new reviews 

review1 = """I loved this movie"""

review2 = """that was the worst movie I've ever seen"""

review3 = """too much violence even for a Bond film"""

review4 = """a captivating recounting of a cherished myth"""

new_reviews = [review1, review2, review3, review4]
In [12]:
# Define a function to prepare the new reviews for use with a model
# and then use the model to predict the sentiment of the new reviews           

def predict_review(model, reviews):
  # Create the sequences
  padding_type='post'
  sample_sequences = tokenizer.texts_to_sequences(reviews)
  reviews_padded = pad_sequences(sample_sequences, padding=padding_type, 
                                 maxlen=max_length) 
  classes = model.predict(reviews_padded)
  for x in range(len(reviews_padded)):
    print(reviews[x])
    print(classes[x])
    print('\n')

predict_review(model, new_reviews)
I loved this movie
[0.37605193]


that was the worst movie I've ever seen
[0.10751317]


too much violence even for a Bond film
[0.03014242]


a captivating recounting of a cherished myth
[0.5916903]


Define a function to train and show the results of models with different layers

In [13]:
def fit_model_and_show_results (model, reviews):
  model.summary()
  history = model.fit(training_padded, training_labels_final, epochs=num_epochs, 
                      validation_data=(validation_padded, validation_labels_final))
  plot_graphs(history, "accuracy")
  plot_graphs(history, "loss")
  predict_review(model, reviews)

Use a CNN

In [14]:
num_epochs = 30

model_cnn = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
    tf.keras.layers.Conv1D(16, 5, activation='relu'),
    tf.keras.layers.GlobalMaxPooling1D(),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

# Default learning rate for the Adam optimizer is 0.001
# Let's slow down the learning rate by 10.
learning_rate = 0.0001
model_cnn.compile(loss='binary_crossentropy',
                  optimizer=tf.keras.optimizers.Adam(learning_rate), 
                  metrics=['accuracy'])

fit_model_and_show_results(model_cnn, new_reviews)
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, 50, 16)            64000     
_________________________________________________________________
conv1d (Conv1D)              (None, 46, 16)            1296      
_________________________________________________________________
global_max_pooling1d (Global (None, 16)                0         
_________________________________________________________________
dense_1 (Dense)              (None, 1)                 17        
=================================================================
Total params: 65,313
Trainable params: 65,313
Non-trainable params: 0
_________________________________________________________________
Epoch 1/30
313/313 [==============================] - 1s 4ms/step - loss: 0.6895 - accuracy: 0.5434 - val_loss: 0.6926 - val_accuracy: 0.5092
Epoch 2/30
313/313 [==============================] - 1s 4ms/step - loss: 0.6825 - accuracy: 0.5590 - val_loss: 0.6922 - val_accuracy: 0.5092
Epoch 3/30
313/313 [==============================] - 1s 4ms/step - loss: 0.6777 - accuracy: 0.5590 - val_loss: 0.6907 - val_accuracy: 0.5092
Epoch 4/30
313/313 [==============================] - 1s 4ms/step - loss: 0.6721 - accuracy: 0.5592 - val_loss: 0.6870 - val_accuracy: 0.5092
Epoch 5/30
313/313 [==============================] - 1s 4ms/step - loss: 0.6640 - accuracy: 0.5671 - val_loss: 0.6803 - val_accuracy: 0.5252
Epoch 6/30
313/313 [==============================] - 1s 4ms/step - loss: 0.6518 - accuracy: 0.6107 - val_loss: 0.6694 - val_accuracy: 0.6089
Epoch 7/30
313/313 [==============================] - 1s 4ms/step - loss: 0.6338 - accuracy: 0.6735 - val_loss: 0.6531 - val_accuracy: 0.6892
Epoch 8/30
313/313 [==============================] - 1s 4ms/step - loss: 0.6086 - accuracy: 0.7331 - val_loss: 0.6306 - val_accuracy: 0.7144
Epoch 9/30
313/313 [==============================] - 1s 4ms/step - loss: 0.5766 - accuracy: 0.7762 - val_loss: 0.6044 - val_accuracy: 0.7328
Epoch 10/30
313/313 [==============================] - 1s 4ms/step - loss: 0.5406 - accuracy: 0.8003 - val_loss: 0.5774 - val_accuracy: 0.7374
Epoch 11/30
313/313 [==============================] - 1s 4ms/step - loss: 0.5036 - accuracy: 0.8162 - val_loss: 0.5526 - val_accuracy: 0.7523
Epoch 12/30
313/313 [==============================] - 1s 4ms/step - loss: 0.4684 - accuracy: 0.8314 - val_loss: 0.5308 - val_accuracy: 0.7615
Epoch 13/30
313/313 [==============================] - 1s 4ms/step - loss: 0.4361 - accuracy: 0.8382 - val_loss: 0.5135 - val_accuracy: 0.7615
Epoch 14/30
313/313 [==============================] - 1s 4ms/step - loss: 0.4073 - accuracy: 0.8471 - val_loss: 0.5000 - val_accuracy: 0.7649
Epoch 15/30
313/313 [==============================] - 1s 4ms/step - loss: 0.3820 - accuracy: 0.8536 - val_loss: 0.4901 - val_accuracy: 0.7729
Epoch 16/30
313/313 [==============================] - 1s 4ms/step - loss: 0.3598 - accuracy: 0.8606 - val_loss: 0.4834 - val_accuracy: 0.7741
Epoch 17/30
313/313 [==============================] - 1s 4ms/step - loss: 0.3402 - accuracy: 0.8669 - val_loss: 0.4796 - val_accuracy: 0.7729
Epoch 18/30
313/313 [==============================] - 1s 4ms/step - loss: 0.3231 - accuracy: 0.8757 - val_loss: 0.4776 - val_accuracy: 0.7683
Epoch 19/30
313/313 [==============================] - 1s 4ms/step - loss: 0.3078 - accuracy: 0.8771 - val_loss: 0.4776 - val_accuracy: 0.7683
Epoch 20/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2941 - accuracy: 0.8840 - val_loss: 0.4789 - val_accuracy: 0.7661
Epoch 21/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2819 - accuracy: 0.8845 - val_loss: 0.4821 - val_accuracy: 0.7638
Epoch 22/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2706 - accuracy: 0.8885 - val_loss: 0.4868 - val_accuracy: 0.7649
Epoch 23/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2607 - accuracy: 0.8912 - val_loss: 0.4914 - val_accuracy: 0.7638
Epoch 24/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2513 - accuracy: 0.8940 - val_loss: 0.4975 - val_accuracy: 0.7626
Epoch 25/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2427 - accuracy: 0.8957 - val_loss: 0.5052 - val_accuracy: 0.7534
Epoch 26/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2348 - accuracy: 0.8998 - val_loss: 0.5116 - val_accuracy: 0.7615
Epoch 27/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2274 - accuracy: 0.9024 - val_loss: 0.5194 - val_accuracy: 0.7626
Epoch 28/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2205 - accuracy: 0.9035 - val_loss: 0.5286 - val_accuracy: 0.7626
Epoch 29/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2143 - accuracy: 0.9073 - val_loss: 0.5379 - val_accuracy: 0.7649
Epoch 30/30
313/313 [==============================] - 1s 4ms/step - loss: 0.2084 - accuracy: 0.9090 - val_loss: 0.5471 - val_accuracy: 0.7638
I loved this movie
[0.8168465]


that was the worst movie I've ever seen
[0.02201137]


too much violence even for a Bond film
[0.00506399]


a captivating recounting of a cherished myth
[0.6824714]


Use a GRU

In [15]:
num_epochs = 30

model_gru = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
    tf.keras.layers.Bidirectional(tf.keras.layers.GRU(32)),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

learning_rate = 0.00003 # slower than the default learning rate
model_gru.compile(loss='binary_crossentropy',
                  optimizer=tf.keras.optimizers.Adam(learning_rate),
                  metrics=['accuracy'])

fit_model_and_show_results(model_gru, new_reviews)
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_2 (Embedding)      (None, 50, 16)            64000     
_________________________________________________________________
bidirectional (Bidirectional (None, 64)                9600      
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 65        
=================================================================
Total params: 73,665
Trainable params: 73,665
Non-trainable params: 0
_________________________________________________________________
Epoch 1/30
313/313 [==============================] - 3s 11ms/step - loss: 0.6906 - accuracy: 0.5568 - val_loss: 0.6931 - val_accuracy: 0.5092
Epoch 2/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6874 - accuracy: 0.5590 - val_loss: 0.6940 - val_accuracy: 0.5092
Epoch 3/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6857 - accuracy: 0.5590 - val_loss: 0.6950 - val_accuracy: 0.5092
Epoch 4/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6847 - accuracy: 0.5590 - val_loss: 0.6958 - val_accuracy: 0.5092
Epoch 5/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6834 - accuracy: 0.5590 - val_loss: 0.6967 - val_accuracy: 0.5092
Epoch 6/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6814 - accuracy: 0.5590 - val_loss: 0.6981 - val_accuracy: 0.5092
Epoch 7/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6783 - accuracy: 0.5590 - val_loss: 0.7002 - val_accuracy: 0.5092
Epoch 8/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6732 - accuracy: 0.5593 - val_loss: 0.7066 - val_accuracy: 0.5092
Epoch 9/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6645 - accuracy: 0.5656 - val_loss: 0.7215 - val_accuracy: 0.5092
Epoch 10/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6517 - accuracy: 0.6056 - val_loss: 0.7315 - val_accuracy: 0.5092
Epoch 11/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6348 - accuracy: 0.6465 - val_loss: 0.7338 - val_accuracy: 0.5092
Epoch 12/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6131 - accuracy: 0.6697 - val_loss: 0.7243 - val_accuracy: 0.5080
Epoch 13/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5838 - accuracy: 0.6914 - val_loss: 0.6755 - val_accuracy: 0.5115
Epoch 14/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5539 - accuracy: 0.7135 - val_loss: 0.6381 - val_accuracy: 0.5275
Epoch 15/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5333 - accuracy: 0.7401 - val_loss: 0.6336 - val_accuracy: 0.5722
Epoch 16/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5166 - accuracy: 0.7494 - val_loss: 0.6355 - val_accuracy: 0.5516
Epoch 17/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5005 - accuracy: 0.7638 - val_loss: 0.6290 - val_accuracy: 0.5849
Epoch 18/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4834 - accuracy: 0.7744 - val_loss: 0.6210 - val_accuracy: 0.6055
Epoch 19/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4692 - accuracy: 0.7882 - val_loss: 0.6060 - val_accuracy: 0.6869
Epoch 20/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4524 - accuracy: 0.7974 - val_loss: 0.5977 - val_accuracy: 0.7190
Epoch 21/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4397 - accuracy: 0.8020 - val_loss: 0.5957 - val_accuracy: 0.7236
Epoch 22/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4263 - accuracy: 0.8095 - val_loss: 0.6010 - val_accuracy: 0.7248
Epoch 23/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4158 - accuracy: 0.8155 - val_loss: 0.5843 - val_accuracy: 0.7454
Epoch 24/30
313/313 [==============================] - 3s 8ms/step - loss: 0.4068 - accuracy: 0.8203 - val_loss: 0.6000 - val_accuracy: 0.7420
Epoch 25/30
313/313 [==============================] - 3s 8ms/step - loss: 0.3974 - accuracy: 0.8260 - val_loss: 0.5887 - val_accuracy: 0.7511
Epoch 26/30
313/313 [==============================] - 3s 9ms/step - loss: 0.3893 - accuracy: 0.8288 - val_loss: 0.6098 - val_accuracy: 0.7431
Epoch 27/30
313/313 [==============================] - 3s 9ms/step - loss: 0.3803 - accuracy: 0.8373 - val_loss: 0.5997 - val_accuracy: 0.7511
Epoch 28/30
313/313 [==============================] - 3s 9ms/step - loss: 0.3738 - accuracy: 0.8402 - val_loss: 0.5968 - val_accuracy: 0.7592
Epoch 29/30
313/313 [==============================] - 3s 9ms/step - loss: 0.3669 - accuracy: 0.8424 - val_loss: 0.6115 - val_accuracy: 0.7477
Epoch 30/30
313/313 [==============================] - 3s 9ms/step - loss: 0.3596 - accuracy: 0.8469 - val_loss: 0.5881 - val_accuracy: 0.7534
I loved this movie
[0.32080284]


that was the worst movie I've ever seen
[0.1174226]


too much violence even for a Bond film
[0.09885525]


a captivating recounting of a cherished myth
[0.5114694]


Add a bidirectional LSTM

In [16]:
num_epochs = 30

model_bidi_lstm = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(embedding_dim)), 
    tf.keras.layers.Dense(1, activation='sigmoid')
])

learning_rate = 0.00003
model_bidi_lstm.compile(loss='binary_crossentropy',
                        optimizer=tf.keras.optimizers.Adam(learning_rate),
                        metrics=['accuracy'])
fit_model_and_show_results(model_bidi_lstm, new_reviews)
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_3 (Embedding)      (None, 50, 16)            64000     
_________________________________________________________________
bidirectional_1 (Bidirection (None, 32)                4224      
_________________________________________________________________
dense_3 (Dense)              (None, 1)                 33        
=================================================================
Total params: 68,257
Trainable params: 68,257
Non-trainable params: 0
_________________________________________________________________
Epoch 1/30
313/313 [==============================] - 4s 11ms/step - loss: 0.6908 - accuracy: 0.5571 - val_loss: 0.6932 - val_accuracy: 0.5092
Epoch 2/30
313/313 [==============================] - 3s 10ms/step - loss: 0.6870 - accuracy: 0.5590 - val_loss: 0.6949 - val_accuracy: 0.5092
Epoch 3/30
313/313 [==============================] - 3s 10ms/step - loss: 0.6843 - accuracy: 0.5590 - val_loss: 0.6979 - val_accuracy: 0.5092
Epoch 4/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6824 - accuracy: 0.5590 - val_loss: 0.7012 - val_accuracy: 0.5092
Epoch 5/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6806 - accuracy: 0.5590 - val_loss: 0.7052 - val_accuracy: 0.5092
Epoch 6/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6784 - accuracy: 0.5590 - val_loss: 0.7088 - val_accuracy: 0.5092
Epoch 7/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6758 - accuracy: 0.5591 - val_loss: 0.7124 - val_accuracy: 0.5092
Epoch 8/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6726 - accuracy: 0.5610 - val_loss: 0.7184 - val_accuracy: 0.5092
Epoch 9/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6686 - accuracy: 0.5701 - val_loss: 0.7211 - val_accuracy: 0.5092
Epoch 10/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6640 - accuracy: 0.5907 - val_loss: 0.7287 - val_accuracy: 0.5092
Epoch 11/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6584 - accuracy: 0.6092 - val_loss: 0.7337 - val_accuracy: 0.5092
Epoch 12/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6515 - accuracy: 0.6235 - val_loss: 0.7355 - val_accuracy: 0.5092
Epoch 13/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6431 - accuracy: 0.6402 - val_loss: 0.7350 - val_accuracy: 0.5092
Epoch 14/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6322 - accuracy: 0.6543 - val_loss: 0.7401 - val_accuracy: 0.5092
Epoch 15/30
313/313 [==============================] - 3s 9ms/step - loss: 0.6180 - accuracy: 0.6659 - val_loss: 0.7352 - val_accuracy: 0.5092
Epoch 16/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5994 - accuracy: 0.6843 - val_loss: 0.7407 - val_accuracy: 0.5092
Epoch 17/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5754 - accuracy: 0.7052 - val_loss: 0.7411 - val_accuracy: 0.5080
Epoch 18/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5515 - accuracy: 0.7271 - val_loss: 0.7281 - val_accuracy: 0.5046
Epoch 19/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5319 - accuracy: 0.7465 - val_loss: 0.7155 - val_accuracy: 0.5046
Epoch 20/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5171 - accuracy: 0.7599 - val_loss: 0.7103 - val_accuracy: 0.5000
Epoch 21/30
313/313 [==============================] - 3s 9ms/step - loss: 0.5033 - accuracy: 0.7698 - val_loss: 0.7089 - val_accuracy: 0.4920
Epoch 22/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4918 - accuracy: 0.7780 - val_loss: 0.7228 - val_accuracy: 0.4908
Epoch 23/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4804 - accuracy: 0.7863 - val_loss: 0.7264 - val_accuracy: 0.5057
Epoch 24/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4705 - accuracy: 0.7917 - val_loss: 0.7385 - val_accuracy: 0.5069
Epoch 25/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4617 - accuracy: 0.7994 - val_loss: 0.7537 - val_accuracy: 0.5011
Epoch 26/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4526 - accuracy: 0.8047 - val_loss: 0.7754 - val_accuracy: 0.4817
Epoch 27/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4446 - accuracy: 0.8086 - val_loss: 0.7863 - val_accuracy: 0.4817
Epoch 28/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4361 - accuracy: 0.8151 - val_loss: 0.8063 - val_accuracy: 0.4748
Epoch 29/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4290 - accuracy: 0.8209 - val_loss: 0.8121 - val_accuracy: 0.4897
Epoch 30/30
313/313 [==============================] - 3s 9ms/step - loss: 0.4212 - accuracy: 0.8218 - val_loss: 0.8247 - val_accuracy: 0.4782
I loved this movie
[0.46079838]


that was the worst movie I've ever seen
[0.21177636]


too much violence even for a Bond film
[0.38008955]


a captivating recounting of a cherished myth
[0.51104355]


Use multiple bidirectional LSTMs

In [17]:
num_epochs = 30

model_multiple_bidi_lstm = tf.keras.Sequential([
    tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(embedding_dim, 
                                                       return_sequences=True)),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(embedding_dim)),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

learning_rate = 0.0003
model_multiple_bidi_lstm.compile(loss='binary_crossentropy',
                                 optimizer=tf.keras.optimizers.Adam(learning_rate),
                                 metrics=['accuracy'])
fit_model_and_show_results(model_multiple_bidi_lstm, new_reviews)
Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_4 (Embedding)      (None, 50, 16)            64000     
_________________________________________________________________
bidirectional_2 (Bidirection (None, 50, 32)            4224      
_________________________________________________________________
bidirectional_3 (Bidirection (None, 32)                6272      
_________________________________________________________________
dense_4 (Dense)              (None, 1)                 33        
=================================================================
Total params: 74,529
Trainable params: 74,529
Non-trainable params: 0
_________________________________________________________________
Epoch 1/30
313/313 [==============================] - 6s 18ms/step - loss: 0.6792 - accuracy: 0.5677 - val_loss: 0.7080 - val_accuracy: 0.5080
Epoch 2/30
313/313 [==============================] - 5s 14ms/step - loss: 0.4833 - accuracy: 0.7603 - val_loss: 0.6775 - val_accuracy: 0.5310
Epoch 3/30
313/313 [==============================] - 5s 15ms/step - loss: 0.3540 - accuracy: 0.8385 - val_loss: 0.6808 - val_accuracy: 0.5608
Epoch 4/30
313/313 [==============================] - 5s 15ms/step - loss: 0.3003 - accuracy: 0.8586 - val_loss: 0.6894 - val_accuracy: 0.4989
Epoch 5/30
313/313 [==============================] - 4s 14ms/step - loss: 0.2732 - accuracy: 0.8752 - val_loss: 0.6847 - val_accuracy: 0.5241
Epoch 6/30
313/313 [==============================] - 5s 15ms/step - loss: 0.2479 - accuracy: 0.8875 - val_loss: 0.9345 - val_accuracy: 0.4966
Epoch 7/30
313/313 [==============================] - 5s 15ms/step - loss: 0.2326 - accuracy: 0.8930 - val_loss: 0.7061 - val_accuracy: 0.5138
Epoch 8/30
313/313 [==============================] - 5s 14ms/step - loss: 0.2196 - accuracy: 0.8992 - val_loss: 0.7168 - val_accuracy: 0.5172
Epoch 9/30
313/313 [==============================] - 5s 14ms/step - loss: 0.2087 - accuracy: 0.9016 - val_loss: 0.7078 - val_accuracy: 0.4977
Epoch 10/30
313/313 [==============================] - 5s 15ms/step - loss: 0.2009 - accuracy: 0.9025 - val_loss: 1.1168 - val_accuracy: 0.4966
Epoch 11/30
313/313 [==============================] - 5s 15ms/step - loss: 0.2002 - accuracy: 0.9046 - val_loss: 0.8402 - val_accuracy: 0.4966
Epoch 12/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1899 - accuracy: 0.9073 - val_loss: 0.9489 - val_accuracy: 0.5000
Epoch 13/30
313/313 [==============================] - 5s 14ms/step - loss: 0.1846 - accuracy: 0.9140 - val_loss: 0.7806 - val_accuracy: 0.5103
Epoch 14/30
313/313 [==============================] - 5s 14ms/step - loss: 0.1789 - accuracy: 0.9140 - val_loss: 0.9045 - val_accuracy: 0.5034
Epoch 15/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1759 - accuracy: 0.9177 - val_loss: 1.0088 - val_accuracy: 0.5103
Epoch 16/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1704 - accuracy: 0.9163 - val_loss: 0.9685 - val_accuracy: 0.5126
Epoch 17/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1690 - accuracy: 0.9153 - val_loss: 0.9409 - val_accuracy: 0.5722
Epoch 18/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1667 - accuracy: 0.9219 - val_loss: 0.9282 - val_accuracy: 0.5413
Epoch 19/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1622 - accuracy: 0.9223 - val_loss: 0.8734 - val_accuracy: 0.4977
Epoch 20/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1626 - accuracy: 0.9232 - val_loss: 1.1524 - val_accuracy: 0.5275
Epoch 21/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1586 - accuracy: 0.9246 - val_loss: 0.8853 - val_accuracy: 0.5482
Epoch 22/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1570 - accuracy: 0.9214 - val_loss: 0.9026 - val_accuracy: 0.5482
Epoch 23/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1549 - accuracy: 0.9217 - val_loss: 1.0543 - val_accuracy: 0.5413
Epoch 24/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1540 - accuracy: 0.9269 - val_loss: 0.9559 - val_accuracy: 0.5367
Epoch 25/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1516 - accuracy: 0.9245 - val_loss: 0.9176 - val_accuracy: 0.5482
Epoch 26/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1519 - accuracy: 0.9242 - val_loss: 0.8955 - val_accuracy: 0.5883
Epoch 27/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1492 - accuracy: 0.9243 - val_loss: 0.8403 - val_accuracy: 0.4885
Epoch 28/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1494 - accuracy: 0.9255 - val_loss: 0.8266 - val_accuracy: 0.4817
Epoch 29/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1478 - accuracy: 0.9251 - val_loss: 0.8842 - val_accuracy: 0.5378
Epoch 30/30
313/313 [==============================] - 5s 15ms/step - loss: 0.1517 - accuracy: 0.9264 - val_loss: 0.8363 - val_accuracy: 0.5206
WARNING:tensorflow:5 out of the last 5 calls to <function Model.make_predict_function.<locals>.predict_function at 0x7fc8d850f378> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/tutorials/customization/performance#python_or_tensor_args and https://www.tensorflow.org/api_docs/python/tf/function for  more details.
WARNING:tensorflow:5 out of the last 5 calls to <function Model.make_predict_function.<locals>.predict_function at 0x7fc8d850f378> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/tutorials/customization/performance#python_or_tensor_args and https://www.tensorflow.org/api_docs/python/tf/function for  more details.
I loved this movie
[0.547561]


that was the worst movie I've ever seen
[0.02361305]


too much violence even for a Bond film
[0.00933948]


a captivating recounting of a cherished myth
[0.9962529]


Try some more reviews

In [18]:
# Write some new reviews 

review1 = """I loved this movie"""

review2 = """that was the worst movie I've ever seen"""

review3 = """too much violence even for a Bond film"""

review4 = """a captivating recounting of a cherished myth"""

review5 = """I saw this movie yesterday and I was feeling low to start with,
 but it was such a wonderful movie that it lifted my spirits and brightened 
 my day, you can\'t go wrong with a movie with Whoopi Goldberg in it."""

review6 = """I don\'t understand why it received an oscar recommendation
 for best movie, it was long and boring"""

review7 = """the scenery was magnificent, the CGI of the dogs was so realistic I
 thought they were played by real dogs even though they talked!"""

review8 = """The ending was so sad and yet so uplifting at the same time. 
 I'm looking for an excuse to see it again"""

review9 = """I had expected so much more from a movie made by the director 
 who made my most favorite movie ever, I was very disappointed in the tedious 
 story"""

review10 = "I wish I could watch this movie every day for the rest of my life"

more_reviews = [review1, review2, review3, review4, review5, review6, review7, 
               review8, review9, review10]
In [19]:
print("============================\n","Embeddings only:\n", "============================")
predict_review(model, more_reviews)
============================
 Embeddings only:
 ============================
I loved this movie
[0.37605193]


that was the worst movie I've ever seen
[0.10751317]


too much violence even for a Bond film
[0.03014242]


a captivating recounting of a cherished myth
[0.5916903]


I saw this movie yesterday and I was feeling low to start with,
 but it was such a wonderful movie that it lifted my spirits and brightened 
 my day, you can't go wrong with a movie with Whoopi Goldberg in it.
[0.28195438]


I don't understand why it received an oscar recommendation
 for best movie, it was long and boring
[0.47447312]


the scenery was magnificent, the CGI of the dogs was so realistic I
 thought they were played by real dogs even though they talked!
[0.26735488]


The ending was so sad and yet so uplifting at the same time. 
 I'm looking for an excuse to see it again
[0.489395]


I had expected so much more from a movie made by the director 
 who made my most favorite movie ever, I was very disappointed in the tedious 
 story
[0.01013994]


I wish I could watch this movie every day for the rest of my life
[0.29397354]


In [20]:
print("============================\n","With CNN\n", "============================")
predict_review(model_cnn, more_reviews)
============================
 With CNN
 ============================
I loved this movie
[0.8168465]


that was the worst movie I've ever seen
[0.02201137]


too much violence even for a Bond film
[0.00506399]


a captivating recounting of a cherished myth
[0.6824714]


I saw this movie yesterday and I was feeling low to start with,
 but it was such a wonderful movie that it lifted my spirits and brightened 
 my day, you can't go wrong with a movie with Whoopi Goldberg in it.
[0.65323055]


I don't understand why it received an oscar recommendation
 for best movie, it was long and boring
[0.91850924]


the scenery was magnificent, the CGI of the dogs was so realistic I
 thought they were played by real dogs even though they talked!
[0.22881518]


The ending was so sad and yet so uplifting at the same time. 
 I'm looking for an excuse to see it again
[0.70266366]


I had expected so much more from a movie made by the director 
 who made my most favorite movie ever, I was very disappointed in the tedious 
 story
[0.05980185]


I wish I could watch this movie every day for the rest of my life
[0.3399837]


In [21]:
print("===========================\n","With bidirectional GRU\n", "============================")
predict_review(model_gru, more_reviews)
===========================
 With bidirectional GRU
 ============================
I loved this movie
[0.32080284]


that was the worst movie I've ever seen
[0.1174226]


too much violence even for a Bond film
[0.09885525]


a captivating recounting of a cherished myth
[0.5114695]


I saw this movie yesterday and I was feeling low to start with,
 but it was such a wonderful movie that it lifted my spirits and brightened 
 my day, you can't go wrong with a movie with Whoopi Goldberg in it.
[0.10725697]


I don't understand why it received an oscar recommendation
 for best movie, it was long and boring
[0.2416777]


the scenery was magnificent, the CGI of the dogs was so realistic I
 thought they were played by real dogs even though they talked!
[0.13711616]


The ending was so sad and yet so uplifting at the same time. 
 I'm looking for an excuse to see it again
[0.5463115]


I had expected so much more from a movie made by the director 
 who made my most favorite movie ever, I was very disappointed in the tedious 
 story
[0.07194155]


I wish I could watch this movie every day for the rest of my life
[0.15554607]


In [22]:
print("===========================\n", "With a single bidirectional LSTM:\n", "===========================")
predict_review(model_bidi_lstm, more_reviews)
===========================
 With a single bidirectional LSTM:
 ===========================
I loved this movie
[0.46079838]


that was the worst movie I've ever seen
[0.21177636]


too much violence even for a Bond film
[0.38008955]


a captivating recounting of a cherished myth
[0.51104355]


I saw this movie yesterday and I was feeling low to start with,
 but it was such a wonderful movie that it lifted my spirits and brightened 
 my day, you can't go wrong with a movie with Whoopi Goldberg in it.
[0.3585305]


I don't understand why it received an oscar recommendation
 for best movie, it was long and boring
[0.5652817]


the scenery was magnificent, the CGI of the dogs was so realistic I
 thought they were played by real dogs even though they talked!
[0.20136029]


The ending was so sad and yet so uplifting at the same time. 
 I'm looking for an excuse to see it again
[0.43636012]


I had expected so much more from a movie made by the director 
 who made my most favorite movie ever, I was very disappointed in the tedious 
 story
[0.19525565]


I wish I could watch this movie every day for the rest of my life
[0.5879127]


In [23]:
print("===========================\n", "With multiple bidirectional LSTM:\n", "==========================")
predict_review(model_multiple_bidi_lstm, more_reviews)
===========================
 With multiple bidirectional LSTM:
 ==========================
I loved this movie
[0.547561]


that was the worst movie I've ever seen
[0.02361305]


too much violence even for a Bond film
[0.00933948]


a captivating recounting of a cherished myth
[0.9962529]


I saw this movie yesterday and I was feeling low to start with,
 but it was such a wonderful movie that it lifted my spirits and brightened 
 my day, you can't go wrong with a movie with Whoopi Goldberg in it.
[0.7593361]


I don't understand why it received an oscar recommendation
 for best movie, it was long and boring
[0.9966543]


the scenery was magnificent, the CGI of the dogs was so realistic I
 thought they were played by real dogs even though they talked!
[0.99291575]


The ending was so sad and yet so uplifting at the same time. 
 I'm looking for an excuse to see it again
[0.99276567]


I had expected so much more from a movie made by the director 
 who made my most favorite movie ever, I was very disappointed in the tedious 
 story
[0.01475957]


I wish I could watch this movie every day for the rest of my life
[0.0172475]